package habitat;

import game.Constants;

import java.io.IOException;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Random;
import java.util.Vector;

import sim.SocialDiversity;
import game.player.Agent;
import game.strategy.Strategy;
import topo.Node;
import topo.Topology;
import topo.TopologyGenerator;
import util.IOTopology;

public class HabitatCreator {

	private int numOfAgents;

	private static int strategyDistrType;

	private String envType;

	Topology topo;

	private int numOfHabitats;

	private Integer[] habitatIDs;

	private Map<Integer, Integer[]> neighHashtable;

	private Random rand = new Random(System.currentTimeMillis());

	private static HabitatCreator HabitatFactory = new HabitatCreator();

	private Map<Integer, Habitat> habitats;

	private Map<Integer, Double> habitatDFs;

	public Map<Integer, Double> getHabitatDFs() {
		return habitatDFs;
	}

	public Map<Integer, Habitat> getHabitats() {
		return habitats;
	}

	public Map<Integer, Integer[]> getNeighHashtable() {
		return neighHashtable;
	}

	private HabitatCreator() {

	}

	/**
	 * @todo: remove habitatDFs
	 **/
	public void createContainerfromTopology(String topoName) {

		topo = null;

		try {
			topo = IOTopology.importTopologyFile(topoName);
		} catch (NumberFormatException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		// / create log file
		envType = topo.getLabel();

		numOfAgents = Constants.NUM_OF_AGENTS;
		strategyDistrType = Constants.STRATEGY_DISTR_TYPE;

		numOfHabitats = topo.getNodes().size();
		habitatIDs = new Integer[numOfHabitats];
		habitatDFs = new HashMap<Integer, Double>();
		neighHashtable = new Hashtable<Integer, Integer[]>();

		for (int i = 0; i < numOfHabitats; i++) {
			Node node = (Node) topo.getNodes().get(i);
			habitatIDs[i] = node.getLabel();
			Integer[] neighbIDs = topo.connectedNodeIDs(node);
			// it keeps all neighbor list of containers
			neighHashtable.put(habitatIDs[i], neighbIDs);
		}
		int containerID;
		// / creation of habitats and agents
		habitats = new HashMap<Integer, Habitat>();
		for (int i = 0; i < numOfHabitats; i++) {
			SocialDiversity sd = SocialDiversity.getDiversityFacotory();
			double sdf = sd.getNext(0, 0);
			// System.out.println("Diversity value : " + sdf);
			habitatDFs.put(habitatIDs[i], sdf);

			containerID = habitatIDs[i];
			// System.out.println(" Create habitat "+i);
			// creates a graph with 20 nodes and 70 edges
			// Topology topo =
			// ScaleFreeNetwork.instance().createScaleFreeNet(4,4,
			// numOfAgents-4);
			Topology topo = TopologyGenerator.createFullConnectedGraph(20);
			// / creation of Player Agents
			Vector<Agent> agents = createAgents(numOfAgents);
			Vector<int[]> intmat = topo.getInterconnectivityMatrix(agents);

			Habitat habitat = new Habitat(containerID, agents, intmat,
					habitatDFs.get(containerID));
			habitats.put(habitat.getID(), habitat);
		}

	}

	private Vector<Agent> createAgents(int numOfAgents) {
		int strategy;
		int agentID;
		Vector<Agent> agents = new Vector<Agent>();

		// for strategies randomly distributed among agents with equally
		// probability
		if (strategyDistrType == 0) {
			for (int i = 0; i < numOfAgents; i++) {
				// 50% C, 50% D
				strategy = rand.nextInt(2);

				agents.add(new Agent(strategy));
			}
		}
		// for strategies randomly distributed among agents with 0.9 probability
		// of Defect
		else if (strategyDistrType == 1) {

			for (int i = 0; i < numOfAgents; i++) {
				// / for 10% Cooperate and %90 Defect
				if (rand.nextDouble() < 0.1)
					strategy = Strategy.COOPERATE;
				else
					strategy = Strategy.DEFECT;

				agents.add(new Agent(strategy));
			}

		}
		return agents;

	}

	public static HabitatCreator getHabitatFactory() {
		return HabitatFactory;
	}

}
